from collections import namedtuple

from simpy import Environment

from osc05.resource.MonitoredFilterStore import MonitoredFilterStore


class Slot:
    def __init__(self, slot_type, component):
        self.slot_type = slot_type
        self.component = component


class ResourceUtil:
    @staticmethod
    def get_stations(env, source_type=(set('1')), capacity=10):
        stations = MonitoredFilterStore(env, capacity=capacity)
        # namedtuple (classname, list of property)
        Server = namedtuple('Server', 'source_type')
        # create Servers filled by s1 as items
        stations.items = []
        # an object with value of 1
        s1 = Server(source_type)

        for i in range(capacity):
            stations.items.append(s1)

        return stations

        # @staticmethod
        # def get_storage_yard(env, component, capacity=100):
        #     stations = MonitoredFilterStore(env, capacity=capacity)
        # stations.items = []
        # # slots for external wall and inner wall
        # slot_type = ('EW', 'IW')
        # #
        # s1 = Slot(slot_type=slot_type,component=None)
        # for i in range(48):
        #     stations.items.append(s1)

        # # slots for floor
        # slot_type = set()
        # slot_type.add('FLR')
        # s1 = Slot(slot_type)
        # for i in range(120):
        #     stations.items.append(s1)
        #
        # # slots for floor
        # slot_type = set()
        # slot_type.add('ST')
        # s1 = Slot(slot_type)
        # for i in range(8):
        #     stations.items.append(s1)

        return stations

    # 'ASS,GRT' team as a multiple-skilled group has 6 people
    @staticmethod
    def get_workers(env, capacity=8):
        workers = MonitoredFilterStore(env, capacity=capacity)
        workers.items = []

        # namedtuple (classname, list of property)
        Server = namedtuple('Server', 'source_type')
        # a worker with skills of assembly and grout
        s1 = Server(('ASSY', 'GRT'))
        # add 5 workers as items
        for i in range(6):
            workers.items.append(s1)

        # a worker with the rebar skill
        s2 = Server({'REB'})
        # add 5 workers as items
        for i in range(2):
            workers.items.append(s2)

        return workers

    # model multiple teams
    # {'ASSY,GRT':5, 'REB':5, 'CARP':5, 'SCAF':5, 'CONC':5}
    # @staticmethod
    # def get_workers1(env,
    #                  worker_dict={'ASS,GRT': 5, 'REB': 5, 'CAP': 5, 'SCF': 5, 'CON': 5},
    #                  capacity=10):
    #     workers = MonitoredFilterStore(env, capacity=capacity)
    #     workers.items = []
    #     for key in worker_dict:
    #         # namedtuple (classname, list of property)
    #         Server = namedtuple('Server', key)
    #         # a worker with two skills
    #         s1 = Server('ASS,GRT')
    #         # add 5 workers as items
    #         for i in range(5):
    #             workers.items.append(s1)
    #
    #         # a worker with two skills
    #         s2 = Server('REB')
    #         # add 5 workers as items
    #         for i in range(capacity):
    #             workers.items.append(s2)
    #     # logging.debug('INIT:items={0}, len={1}'.format(stations.items, len(stations.items)))
    #     return workers

    @staticmethod
    # release resource list
    def release_occupied_resources(self, resource_pool, message, occupied_resources):
        # release occupied workers
        for occupied_worker in occupied_resources:
            # release the worker from worker pool
            yield resource_pool.put(self, message, occupied_worker)

    @staticmethod
    # occupy and return the workers with a matching skill
    def request_source_items(self, resource_pool: object, message, source_type: object, source_num=1) -> object:
        # ResourceUtil.lock.acquire()
        # request workers according to the required skill
        occupied_resource_item_list = []

        print('@', self.construction_site.env.now, self.name, message, ' tries to request and ITEM is LOCKED')
        # print("items before =" + str(self.construction_site.workers.items))
        for i in range(source_num):
            # occupy the worker with a matching skill
            occupied_resource_item = yield resource_pool.get(self, message,
                                                             lambda item: source_type in item.source_type)
            yield self.construction_site.env.timeout(0.01)
            print('@', self.construction_site.env.now, self.name,
                  "got resource_item=" + str(occupied_resource_item))
            occupied_resource_item_list.append(occupied_resource_item)
        # ResourceUtil.lock.release()

        return occupied_resource_item_list


if __name__ == '__main__':
    env = Environment()
    worker_team = ResourceUtil.get_workers(env)
    for worker in worker_team.items:
        print(worker.skills)
        print('GRT' in worker.skills)
        print('ASS' in worker.skills)
        print('ASS1' in worker.skills)
        print('AS' in worker.skills)
    print(worker_team)
